home *** CD-ROM | disk | FTP | other *** search
/ Gigarom 1 / Gigarom Macintosh Archives (Quantum Leap)(CDRM1080320)(1993).iso / FILES / HYP / C-D / DartmouthXCMDs.cpt / Dartmouth XCMDs Vol 1&2 / card_6277.txt < prev    next >
Text File  |  1989-02-26  |  25KB  |  881 lines

  1. -- card: 6277 from stack: in
  2. -- bmap block id: 8749
  3. -- flags: 0000
  4. -- background id: 8327
  5. -- name: XScrollBox
  6. ----- HyperTalk script -----
  7. on opencard
  8.   set the visible of field 1 to false -- background field
  9.   set the scroll of card field 1 to 0
  10.   set the scroll of card field 2 to 0
  11. end opencard
  12. on closecard
  13.   set the visible of field 1 to true
  14. end closecard
  15.  
  16.  
  17. -- part 2 (field)
  18. -- low flags: 00
  19. -- high flags: 4007
  20. -- rect: left=384 top=62 right=290 bottom=491
  21. -- title width / last selected line: 0
  22. -- icon id / first selected line: 0 / 0
  23. -- text alignment: 0
  24. -- font id: 3
  25. -- text size: 9
  26. -- style flags: 0
  27. -- line height: 12
  28. -- part name: scroller
  29.  
  30.  
  31. -- part 3 (button)
  32. -- low flags: 00
  33. -- high flags: 8003
  34. -- rect: left=76 top=298 right=320 bottom=176
  35. -- title width / last selected line: 0
  36. -- icon id / first selected line: 0 / 0
  37. -- text alignment: 1
  38. -- font id: 0
  39. -- text size: 12
  40. -- style flags: 0
  41. -- line height: 16
  42. -- part name: XScrollBox
  43. ----- HyperTalk script -----
  44. on mouseUp
  45.   put empty into msg
  46.   get XScrollBox(2,"Choose one of these:",card field "scroller","Help")
  47.   if it is "Help" then
  48.     put "You pushed the 'Help' button."
  49.   else if it is empty then
  50.     put "You pushed the 'Cancel' button."
  51.   else
  52.     put "Your choice was: " & it
  53.   end if
  54. end mouseUp
  55.  
  56.  
  57.  
  58. -- part 5 (field)
  59. -- low flags: 00
  60. -- high flags: 2007
  61. -- rect: left=18 top=32 right=290 bottom=384
  62. -- title width / last selected line: 0
  63. -- icon id / first selected line: 0 / 0
  64. -- text alignment: 0
  65. -- font id: 20
  66. -- text size: 12
  67. -- style flags: 0
  68. -- line height: 16
  69. -- part name: XCMD Text
  70.  
  71.  
  72. -- part 6 (button)
  73. -- low flags: 00
  74. -- high flags: 8003
  75. -- rect: left=304 top=299 right=321 bottom=425
  76. -- title width / last selected line: 0
  77. -- icon id / first selected line: 0 / 0
  78. -- text alignment: 1
  79. -- font id: 0
  80. -- text size: 12
  81. -- style flags: 0
  82. -- line height: 16
  83. -- part name: Show LSC Source
  84. ----- HyperTalk script -----
  85. on mouseUp
  86.   get the visible of card field "source"
  87.   set the visible of card field "source" to not it
  88.   if it is false then
  89.     set the name of me to "Hide LSC Source"
  90.   else
  91.     set the name of me to "Show LSC Source"
  92.   end if
  93. end mouseUp
  94.  
  95.  
  96.  
  97. -- part 7 (field)
  98. -- low flags: 81
  99. -- high flags: 0007
  100. -- rect: left=18 top=31 right=290 bottom=489
  101. -- title width / last selected line: 0
  102. -- icon id / first selected line: 0 / 0
  103. -- text alignment: 0
  104. -- font id: 3
  105. -- text size: 10
  106. -- style flags: 0
  107. -- line height: 13
  108. -- part name: source
  109.  
  110.  
  111. -- part contents for card part 2
  112. ----- text -----
  113. able
  114. baker
  115. charlie
  116. dog
  117. ernest
  118. fox
  119. gamma
  120. horse
  121. ice cream
  122. jumping jack flash
  123. knockwurst
  124. liver
  125. monkey
  126. no way, jose
  127. occularity
  128. penelope
  129. qwerty
  130. rapscallion
  131. salubrious
  132. twinkle toes
  133. underwhelmed
  134. vermin
  135. wascally wabbit
  136. yokel
  137. zenzational
  138.  
  139. -- part contents for card part 5
  140. ----- text -----
  141. XScrollBox version 1.4
  142. Roger Brown
  143.  
  144. XScrollBox is a HyperCard XFCN that creates a scrolling selection dialog box from any multi-lined container.  Each line of the container is made into a selection line in the dialog. Only one line can be selected. 
  145.  
  146. The return value has two items: the number of the selection and the text of the selection. These are separated by commas as in normal HyperCard format. 
  147.    
  148. Selection can be made by :
  149.    1. double-clicking on a line.
  150.    2. single-clicking on a line, then pressing the OK button.
  151.    3. single-clicking on a line, then pressing the Return key.
  152.    4. typing the first letter(s) of a selection, then doing 1,2, or 3.
  153.      (Note: type selection assumes that the lines are ordere alphabetically)
  154.    5. scrolling with up and down arrow keys, then doing 1,2 or 3.
  155.    
  156.    If the Cancel button is pressed, a null string is returned.
  157.    
  158.    It requires that the DITL and DLOG resources (1345) packaged with 
  159.    it are in the stack.
  160.    
  161.   The dialog is centered on the screen and sized to hold the width of the   
  162.    longest line and/or the prompt line, whichever is widest. It will not 
  163.    overrun the width of a  Mac+ screen.
  164.  
  165. INVOKING XScrollBox
  166.  
  167.   get XScrollBox(first,prompt,container,userButton)
  168.         
  169.    where   first  is a default selection in the list - either a number or a     
  170.                    text string (0 if none).
  171.                 prompt is a string to prompt the user. This appears at the top                      
  172.                    of the dialog box.
  173.                 container is any hypercard container (field, variable), 
  174.                    presumed to be multi-lined.
  175.                 UserButton  is the name for an optional author specified 
  176.                    button. If this button is pressed, its name is returned             
  177.                    further processing by the script.  
  178.                    
  179.  
  180. EXAMPLE
  181.  
  182.  ex.  get XScrollBox(1,"Choose:",card field 1,"Help")
  183.         if OK is pressed, returns : 1,text of line 1 of card field 1
  184.  
  185.  
  186. REVISION HISTORY
  187. 1.1 center dialog box on any size screen
  188. 1.2 - add selection scrolling by typing and by cursor keys
  189. 1.3 - add text of chosen item to return value
  190. 1.4 -- 3/2/88   add optional user button
  191.  
  192.  
  193. -- part contents for card part 7
  194. ----- text -----
  195.  
  196. /* XSCrollBox1.4.c */
  197. /* ¬© Trustees of Dartmouth College */
  198. /* written in LightSpeed C  ¬© Think Technologies, Inc */
  199. /* by Roger Brown 3/2/88  Courseware Development Group */
  200.  
  201. /* This is a HyperCard XFCN that creates a scrolling selection dialog box from
  202.    any multi-lined container. Syntax is:
  203.    
  204.         get XScrollBox(first,prompt,container,userButton)
  205.    
  206.    ex.      get XScrollBox(1,"Choose:",card field 1,"Help")
  207.   
  208.    returns: 1,text of line 1 of card field 1
  209.    
  210.    where    first       is a default selection in the list - either a number
  211.                         or a text string (0 if none).
  212.             prompt      is a string to prompt the user. This appears at the
  213.                         top of the dialog box.
  214.             container   is any hypercard container (field, variable), presumed to be 
  215.                         multi-lined.
  216.             UserButton  is the name for an optional author specified button.
  217.                         If this button is pressed, its name is returned
  218.                         for further processing by the script.  
  219.                     
  220.    Each line of the container is made into a selection line in the
  221.    dialog. Only one line can be selected. 
  222.    
  223.    The return value has two items: the number of the selection and the text of
  224.    the selection. These are separated by commas as in normal HyperCard format. 
  225.    
  226.    Selection can be made by:
  227.    
  228.    1. double-clicking on a line.
  229.    2. single-clicking on a line, then pressing the OK button.
  230.    3. single-clicking on a line, then pressing the Return key.
  231.    4. typing the first letter(s) of a selection, then doing 1,2, or 3.
  232.       (Note: type selection assumes that the lines are ordered alphabetically)
  233.    5. scrolling with up and down arrow keys, then doing 1,2 or 3.
  234.    
  235.    If the Cancel button is pressed, a null string is returned.
  236.    
  237.    It requires that the DITL and DLOG resources packaged with it are in the stack.
  238.    
  239.    The dialog box is centered in the card window.
  240.    
  241.    To compile: create a project with this and MacTraps. Build as code resource type
  242.    XFCN, ID 1345, name XScrollBox.
  243. */
  244.  
  245.  
  246.  
  247. #include "stddata_ctype.c"
  248. #include "QuickDraw.h"
  249. #include "EventMgr.h"
  250. #include "WindowMgr.h"
  251. #include "ResourceMgr.h"
  252. #include "ControlMgr.h"
  253. #include "DialogMgr.h"
  254. #include "strings.c"
  255. #include "ListMgr.h"
  256. #include "ToolboxUtil.h"
  257. #include "HyperXCmd.h"
  258. #include "XCmdGlue.inc.c"
  259.  
  260.  
  261. #define FALSE 0
  262. #define TRUE !FALSE
  263.  
  264. /*  The following assembly routines manage register A4. They are required because
  265.     we use global variables and access them from within functions that are passed
  266.     as parameters to other functions. This is a LSC convention. */
  267.     
  268. #define RememberA4() _A4_(1)
  269. #define XCMDSetupA4() asm { move.l A4,-(sp) };_A4_(0)
  270. #define XCMDRestoreA4() asm { move.l (sp)+,A4 }
  271.  
  272. /* globals */
  273.  
  274. #define kOKbutton 1
  275. #define kCancel 2
  276. #define kPrompt 3
  277. #define kListItem 4
  278. #define kOutliner 5
  279. #define kUserButton 6
  280. #define kTyping 99
  281.  
  282. int kScrollBarWidth = 15;
  283.  
  284. int kStdLDEF = 0;
  285. int kDialogId = 1345;
  286. int kStringListId = 1345;
  287.  
  288. int gCellWidth;
  289. int gCellHeight = 16;
  290.  
  291. Rect dialogRect,listRect,cardRect;
  292. ListHandle theList;
  293. DialogPtr theListDialog;
  294. Str255 theResult,userButton;
  295. long theStartWith;
  296. Str255 startString;
  297. char startIsString;
  298. Handle resultHandle;
  299. CursHandle theCursor;
  300. char collector[32];
  301. int charPos;
  302. long charTime;
  303.  
  304. /* return max of 2 integers */
  305.  
  306. max(a,b)
  307. int a,b;
  308.     if (a>b) return a;
  309.     return b;
  310. }
  311.  
  312. /* return min of 2 integers */
  313.  
  314. min(a,b)
  315. {
  316.     if (a<b) return a;
  317.     return b;
  318. }
  319.  
  320. /* Need this register management if you use global variables inside
  321.    procedures that are parameters to other procedures */
  322.    
  323. _A4_(remember)
  324. {   
  325.     asm {
  326.             bra.s @1
  327.     save:   dc.l   0 ;keep saved A4 here
  328.     @1      lea   @save,a1
  329.         }
  330.         if (remember)
  331.             asm {move.l A0,(A1) }
  332.         else
  333.             asm {move.l (A1),A4 }
  334. }
  335.  
  336. /* Get HyperCard comma delimited item i from item list string s. */
  337.  
  338. int GetHCItem(s,i)
  339. char *s;
  340. int i;
  341. {
  342.     int c,len,count,j;
  343.     char temp[32];
  344.     long it;
  345.     
  346.     count = j = 0;
  347.     len = strlen(s);
  348.     for (c=0;c<len;c++) {
  349.         if (s[c]==',') {
  350.             count = count + 1;
  351.             if (count==i) break;
  352.             j = 0;
  353.         }
  354.         else {
  355.             temp[j] = s[c];
  356.             j++;
  357.             if (c==(len-1)) {     /* last item, no comma */
  358.                 count = count+1;
  359.                 break;
  360.             }
  361.         }
  362.     }
  363.     if (count < i) strcpy(temp,"");  /* no item there */
  364.     temp[j] = 0;
  365.     CtoPstr(temp);
  366.     StringToNum(temp,&it);
  367.     return (int)it;
  368. }
  369.  
  370. /* Get the coordiates of the HyperCard card window so we can center the dialog on it. */
  371.  
  372. GetCardRect(paramPtr,itsRect)
  373. XCmdBlockPtr    paramPtr;
  374. Rect *itsRect;
  375. {
  376.     Handle theResult;
  377.     long len;
  378.     Str255 str;
  379.     int i;
  380.     
  381.     strcpy(str,"the rect of card window");
  382.     CtoPstr(str);
  383.     theResult = EvalExpr(paramPtr,str);
  384.     len = GetHandleSize(theResult);
  385.     HLock(theResult);
  386.     BlockMove(*theResult,str,len);
  387.     HUnlock(theResult);
  388.     DisposHandle(theResult);
  389.     itsRect->left = GetHCItem(str,1);
  390.     itsRect->top = GetHCItem(str,2);
  391.     itsRect->right = GetHCItem(str,3);
  392.     itsRect->bottom = GetHCItem(str,4);
  393. }
  394.  
  395. /* user item in dialog box to outline the default (ok) button */
  396.  
  397. pascal void OutlineButton (myWindow,itemNo)
  398. WindowPtr myWindow;
  399. int itemNo;
  400. {
  401.     int iType;
  402.     Handle iHandle;
  403.     Rect iBox;
  404.     
  405.     XCMDSetupA4();
  406.     GetDItem(theListDialog, kOKbutton, &iType, &iHandle, &iBox);
  407.     InsetRect(&iBox, -4, -4);
  408.     PenSize(3, 3);
  409.     FrameRoundRect(&iBox, 16, 16);
  410.     PenNormal();
  411.     XCMDRestoreA4();
  412. }
  413.  
  414. /* User item in dialog box to display the selectin list */
  415.  
  416. pascal void DrawListItem (myWindow,itemNo)
  417. WindowPtr myWindow;
  418. int itemNo;
  419. /* draw the selection list */
  420. {
  421.     RgnHandle theRgn;
  422.     Rect listFrame;
  423.     
  424.     XCMDSetupA4();
  425.     listFrame = (**theList).rView;
  426.     InsetRect(&listFrame, -1, -1);
  427.     FrameRect(&listFrame);
  428.     theRgn = NewRgn();
  429.     RectRgn(theRgn, &(*theListDialog).portRect);
  430.     LUpdate(theRgn, theList);
  431.     DisposeRgn(theRgn);
  432.     XCMDRestoreA4();
  433. }
  434.  
  435. /* string selection logic for selection via typed characters */
  436.  
  437. pascal int MySelect(aPtr,bPtr,aLen,bLen)
  438. Ptr aPtr,bPtr;int aLen,bLen;
  439. {
  440.     if (IUMagString(aPtr,bPtr,aLen,bLen) ==1) return 0;
  441.     return 1;
  442. }
  443.  
  444. /* scroll selection list up or down */
  445.  
  446. VerticalScroll(c)
  447. char c;
  448. {
  449.     Cell oldCell,aCell;
  450.         
  451.     XCMDSetupA4();
  452.     SetPt(&oldCell,0,0);
  453.     if (!LGetSelect(TRUE,&oldCell,theList)) {  /* get current selection */
  454.         SysBeep(0); /* no current selection */
  455.         return;
  456.     }
  457.     if (c==30) {
  458.         SetPt(&aCell,0,max(0,oldCell.v-1));
  459.     }
  460.     else if (c==31) {
  461.         SetPt(&aCell,0,min((**theList).dataBounds.bottom-1,oldCell.v+1));
  462.     }
  463.     if (EqualPt(oldCell,aCell)==1) {
  464.         SysBeep(0);
  465.         return;
  466.     }
  467.     LSetSelect(FALSE,oldCell,theList);  /* clear current selection */
  468.     LSetSelect(TRUE,aCell,theList);     /* set the new one */   
  469.     LAutoScroll(theList);
  470.     XCMDRestoreA4();
  471. }
  472.  
  473. /* Select by typing - a filter proc for ModalDialog. Simulates SGGetFile dialog action. */
  474.  
  475. pascal char NameSelect(theDialog,theEvent,itemHit)
  476. DialogPtr theDialog;EventRecord *theEvent;int *itemHit;
  477. {
  478.     int c;
  479.     long dummy;
  480.     int iType;
  481.     Handle iHandle;
  482.     Rect iBox;
  483.     char result;
  484.     
  485.     XCMDSetupA4();
  486.     result = FALSE;
  487.     if ((theEvent->what == keyDown)||(theEvent->what == autoKey)) {
  488.         if (TickCount() > charTime) charPos = 0;
  489.         collector[charPos] = BitAnd(theEvent->message,charCodeMask);
  490.         if ((collector[charPos] ==13)||(collector[charPos]==3)) {  /* is CR, use as normal */
  491.             *itemHit = 1;
  492.             GetDItem(theListDialog, kOKbutton, &iType, &iHandle, &iBox);
  493.             HiliteControl(iHandle,inButton);
  494.             result = TRUE;
  495.         }
  496.         else if ((collector[charPos]==31)||(collector[charPos]==30)) {  /* cursor up/down */
  497.             VerticalScroll(collector[charPos]);
  498.             charPos = 0;
  499.         }
  500.         else {
  501.             charPos++;
  502.             collector[charPos] = 0;
  503.             *itemHit = 99;
  504.             result = TRUE;
  505.             charTime = TickCount()+45;
  506.         }
  507.     }
  508.     XCMDRestoreA4();
  509.     return result;
  510. }
  511.  
  512. /* Create, size, center, and fill in the selection box. Retuens 0 if any errors occur. */
  513.  
  514. int SetupScrollBox (prompt,theField)
  515. char *prompt;
  516. char *theField;
  517. {
  518.     Rect dataBounds, itemBox,tempRect;
  519.     char doVScroll, doHScroll;
  520.     Point cellSize;
  521.     Cell aCell,oldCell;
  522.     int i,j, itemType,x,y;
  523.     ControlHandle itemHandle;
  524.     Str255 aString;
  525.     long len;
  526.     int fieldLen;
  527.     int numLines,lineLen,maxLen,row;
  528.     char done,c;
  529.     int screenCenterX,screenCenterY;
  530.     int dialogWidth;
  531.     int dialogCenterX,dialogCenterY;
  532.     int itemWidth,itemHeight;
  533.     int itemHit;
  534.     GrafPtr gp;
  535.     Handle tempHandle;
  536.     int numButtons;
  537.     
  538.     XCMDSetupA4();
  539.     if (strlen(userButton)>0) numButtons = 3;
  540.     else numButtons = 2;
  541.     
  542.     /* size the dialog box */
  543.     
  544.     dialogWidth = 200+8*strlen(userButton); /* minimum width to fit buttons at bottom */
  545.                                /* make sure the prompt fits */
  546.     dialogWidth = max(dialogWidth,strlen(prompt)*8+20);
  547.         
  548.     /* find the longest line */
  549.     
  550.     lineLen = maxLen = numLines = 0;
  551.     fieldLen = strlen(theField);
  552.     for (i=0;i<fieldLen;i++) {
  553.         c = theField[i];
  554.         if ((c ==13)||(i==(fieldLen-1))) {
  555.             maxLen = max(lineLen,maxLen);
  556.             lineLen = 0;
  557.             numLines++;
  558.         }
  559.         else lineLen++;
  560.     }
  561.     gCellWidth = maxLen*8;
  562.     
  563.     /* size it to have 10 lines visible and 8 pixels per character */
  564.     /* leave room at the top for the prompt and at the bottom for
  565.        the OK button */
  566.        
  567.     dialogWidth = max(dialogWidth,gCellWidth+20+16);
  568.     dialogWidth = min(dialogWidth,490);  /* chop to screen width */
  569.     
  570.     gCellWidth = dialogWidth-20-16;
  571.     
  572.     SetRect(&dialogRect,0,0,dialogWidth,75+(10*gCellHeight));
  573.     SetRect(&listRect,10,30,10+gCellWidth,30+(10*gCellHeight));
  574.     
  575.     /* now center it in the current port */
  576.         
  577.     screenCenterX = cardRect.left + (cardRect.right - cardRect.left)/2;
  578.     screenCenterY = cardRect.top + (cardRect.bottom - cardRect.top)/2;
  579.  
  580.     dialogCenterX = dialogRect.left + (dialogRect.right-dialogRect.left)/2;
  581.     dialogCenterY = dialogRect.top + (dialogRect.bottom-dialogRect.top)/2;
  582.             
  583.     OffsetRect(&dialogRect,screenCenterX-dialogCenterX,
  584.                 screenCenterY-dialogCenterY);
  585.     
  586.     dialogCenterX = dialogRect.left + (dialogRect.right-dialogRect.left)/2;
  587.     dialogCenterY = dialogRect.top + (dialogRect.bottom-dialogRect.top)/2;
  588.     
  589.     /* now get the dialog resource */
  590.     
  591.     tempHandle = GetResource('DLOG',kDialogId);
  592.     if (tempHandle==NULL) {
  593.         XCMDRestoreA4();
  594.         return 0;
  595.     }
  596.  
  597.     theListDialog = GetNewDialog(kDialogId, NULL,(WindowPtr)NULL);
  598.  
  599.     /* size it and center it */
  600.     
  601.     MoveWindow(theListDialog,dialogRect.left,dialogRect.top,FALSE);
  602.     SizeWindow(theListDialog,dialogRect.right-dialogRect.left,
  603.                 dialogRect.bottom-dialogRect.top,FALSE);
  604.     
  605.     /* adjust the ok button */
  606.     
  607.     GetDItem(theListDialog,kOKbutton,&itemType,&itemHandle,&itemBox);
  608.     itemWidth = (itemBox.right-itemBox.left);
  609.     itemHeight = (itemBox.bottom-itemBox.top);
  610.     x = listRect.left  + 
  611.         (listRect.right+16-listRect.left)/(numButtons*2) - itemWidth/2;
  612.     y = listRect.bottom + 15;   
  613.     SetRect(&itemBox,x,y,x+itemWidth,y+itemHeight); 
  614.     MoveControl(itemHandle,itemBox.left,itemBox.top);
  615.     SetDItem(theListDialog,kOKbutton,itemType,itemHandle,&itemBox);
  616.         
  617.     /* adjust the cancel button */
  618.     
  619.     GetDItem(theListDialog,kCancel,&itemType,&itemHandle,&itemBox);
  620.     itemWidth = (itemBox.right-itemBox.left);
  621.     itemHeight = (itemBox.bottom-itemBox.top);
  622.     x = listRect.left  + 
  623.         (numButtons*2-1)*(listRect.right+16-listRect.left)/(numButtons*2)
  624.          - itemWidth/2;
  625.     y = listRect.bottom + 15;   
  626.     SetRect(&itemBox,x,y,x+itemWidth+100,y+itemHeight); 
  627.     MoveControl(itemHandle,itemBox.left,itemBox.top);
  628.     SetDItem(theListDialog,kCancel,itemType,itemHandle,&itemBox);
  629.     
  630.     /* set up the user button if there is one */
  631.         
  632.     GetDItem(theListDialog,kUserButton,&itemType,&itemHandle,&itemBox);
  633.     CtoPstr(userButton);
  634.     SetCTitle(itemHandle,userButton);
  635.     itemHeight = (itemBox.bottom-itemBox.top);
  636.     itemWidth = 8*strlen(userButton);
  637.     x = listRect.left  + 
  638.         (numButtons*(listRect.right+16-listRect.left)/(numButtons*2))
  639.         - itemWidth/2;
  640.     x = x + 2;        /* to balance OK button outliner */
  641.     y = listRect.bottom + 15;
  642.     SetRect(&itemBox,x,y,x+itemWidth,y+itemHeight);
  643.     MoveControl(itemHandle,itemBox.left,itemBox.top);
  644.     SizeControl(itemHandle,itemWidth,itemHeight);
  645.     SetDItem(theListDialog,kUserButton,itemType,itemHandle,&itemBox);
  646.     PtoCstr(userButton);
  647.  
  648.     
  649.     /* adjust the prompt string and fill it in */
  650.     
  651.     GetDItem(theListDialog,kPrompt,&itemType,&itemHandle,&itemBox);
  652.     itemWidth = strlen(prompt)*8;
  653.     CtoPstr(prompt);    
  654.     SetIText(itemHandle,prompt);
  655.     itemHeight = (itemBox.bottom-itemBox.top);
  656.     x = listRect.left  + 
  657.         (listRect.right+16 - listRect.left)/2 - itemWidth/2;
  658.     y = listRect.top - 5;   
  659.     SetRect(&itemBox,x,y-itemHeight,x+itemWidth,y);     
  660.     SetDItem(theListDialog,kPrompt,itemType,itemHandle,&itemBox);
  661.  
  662.     
  663.     /* now create the text list */
  664.     
  665.     SetRect(&dataBounds, 0, 0, 1, numLines);
  666.     SetPt(&cellSize, gCellWidth, gCellHeight);
  667.     theList = LNew(&listRect, &dataBounds, cellSize,
  668.          kStdLDEF, (WindowPtr)theListDialog, FALSE, FALSE, FALSE, TRUE);
  669.     (**theList).selFlags = lOnlyOne;
  670.      
  671.     /* now fill in its text */
  672.     /* squeeze out control characters 2/27/88 */
  673.     
  674.     j = 0;row = 0;
  675.     for (i=0;i<fieldLen;i++) {
  676.         if (theField[i] > 31) {
  677.             aString[j] = theField[i];
  678.             j++;
  679.         }
  680.         if ((theField[i] ==13)||(i==(fieldLen-1))) {
  681.             aString[j] = 0;
  682.             SetPt(&aCell,0,row);
  683.             row ++;
  684.             lineLen = strlen(aString);
  685.             LSetCell(&aString[0], lineLen, aCell, theList);
  686.             j = 0;
  687.         } 
  688.     }
  689.     if (startIsString) {
  690.         SetPt(&oldCell,0,0);
  691.         LGetSelect(TRUE,&oldCell,theList);  /* get current selection*/
  692.         SetPt(&aCell,0,0);
  693.         if (LSearch(startString,strlen(startString),MySelect,&aCell,theList)) {
  694.             if (!EqualPt(oldCell,aCell)) {
  695.                 LSetSelect(FALSE,oldCell,theList);  /* clear current selection */
  696.                 LSetSelect(TRUE,aCell,theList);     /* set the new one */   
  697.                 LAutoScroll(theList);
  698.             }
  699.         }
  700.     }
  701.     else if ((theStartWith > 0)&&(theStartWith<numLines)); {
  702.         SetPt(&aCell, 0,theStartWith-1);
  703.         LSetSelect(TRUE, aCell, theList);
  704.         if (theStartWith>10) LAutoScroll(theList);
  705.     }
  706.     LDoDraw(TRUE, theList);
  707.     
  708.     
  709.     /* now complete the two user items of the dialog */
  710.     
  711.     itemBox = listRect;
  712.     itemBox.right = itemBox.right + kScrollBarWidth;
  713.  
  714.     SetDItem(theListDialog, kListItem, userItem, DrawListItem, &itemBox);
  715.     GetDItem(theListDialog,kOKbutton,&itemType,&itemHandle,&itemBox);
  716.     SetDItem(theListDialog, kOutliner, userItem + itemDisable, OutlineButton, &itemBox);
  717.     
  718.     /* present the window up front */
  719.     
  720.     ShowWindow(theListDialog);
  721.     BringToFront(theListDialog);
  722.  
  723.     XCMDRestoreA4();
  724.     return 1;
  725. }
  726.  
  727. DoListDialog ()
  728.  
  729. /* pose the dialog and handle it */
  730.  
  731. {
  732.     int itemHit;
  733.     Point aPoint;
  734.     Cell oldCell,aCell;
  735.     
  736.     itemHit = charPos = 0;
  737.     while (1) {
  738.         ModalDialog(NameSelect, &itemHit);
  739.         switch (itemHit) {
  740.             case kOKbutton :
  741.                 return 1;
  742.             break;
  743.             case kCancel:
  744.                 return 0;
  745.             break;
  746.             case kListItem:
  747.                 SetPort(theListDialog);
  748.                 GetMouse(&aPoint);
  749.                 if (LClick(aPoint, 0, theList)) return 1;
  750.             break;
  751.             case kUserButton:
  752.                 return 2;
  753.             break;
  754.             case kTyping:
  755.                 SetPt(&oldCell,0,0);
  756.                 LGetSelect(TRUE,&oldCell,theList);  /* get current selection*/
  757.                 SetPt(&aCell,0,0);
  758.                 if (LSearch(collector,strlen(collector),MySelect,&aCell,theList)) {
  759.                     if (!EqualPt(oldCell,aCell)) {
  760.                         LSetSelect(FALSE,oldCell,theList);  /* clear current selection */
  761.                         LSetSelect(TRUE,aCell,theList);     /* set the new one */   
  762.                         LAutoScroll(theList);
  763.                     }
  764.                 }
  765.             break;
  766.         }
  767.     }
  768. }
  769.  
  770. /* get the text of the selection made */
  771.  
  772. GetListSelection (aString)
  773. char *aString;
  774. {
  775.     char someSelect;
  776.     Cell aCell;
  777.     int stringLength,t,b,i;
  778.     Str255 num;
  779.     long n;
  780.     
  781.     SetPt(&aCell, 0, 0);
  782.     someSelect = LGetSelect(TRUE, &aCell, theList);
  783.     if (someSelect==TRUE) {
  784.         stringLength = 255;
  785.         LGetCell(aString, &stringLength, aCell, theList);
  786.         n = aCell.v+1;
  787.         NumToString(n,num);
  788.         PtoCstr(num);
  789.         *(aString+stringLength) = 0;
  790.         strcat(num,",");
  791.         strcat(num,aString);
  792.         strcpy(aString,num);
  793.     }
  794.     else {
  795.         strcpy(aString,"");
  796.     }
  797. }
  798.  
  799. /* clean up memory */
  800.  
  801. PrepareToExit()
  802. {   
  803.     if (theList != NULL) LDispose(theList);
  804.     if (theListDialog != NULL) DisposDialog(theListDialog);
  805. }
  806.  
  807. /* create scroll box, present it, return user's selection */
  808.  
  809. pascal void XScrollBox(paramPtr)
  810. XCmdBlockPtr    paramPtr;
  811. {   
  812.     Str255 result;
  813.     Ptr start;
  814.     Ptr thePrompt;
  815.     Ptr theField;
  816.     Ptr theUserButton;
  817.     int status,i;
  818.     Size len;
  819.     
  820.     theCursor = GetCursor(watchCursor);
  821.     SetCursor(*theCursor);
  822.     for (i=0;i<5;i++) {
  823.         MoveHHi(paramPtr->params[i]);
  824.         HLock(paramPtr->params[i]);
  825.     }
  826.     start = *(paramPtr->params[0]);
  827.     startIsString = TRUE;
  828.     for (i=0;i<strlen(start);i++) {
  829.         if (!isalpha(start[i])) {
  830.             startIsString = FALSE;
  831.             break;
  832.         }
  833.     }
  834.     if (startIsString) strcpy(startString,start);
  835.     else {
  836.         CtoPstr(start);  
  837.         StringToNum(start,&theStartWith);
  838.     }
  839.     thePrompt = *(paramPtr->params[1]);
  840.     theField = *(paramPtr->params[2]);
  841.     theUserButton = *(paramPtr->params[3]);
  842.     if (GetHandleSize(paramPtr->params[3])>0)
  843.         strcpy(userButton,theUserButton);
  844.     else strcpy(userButton,"");
  845.         
  846.     GetCardRect(paramPtr,&cardRect);
  847.     status = SetupScrollBox(thePrompt,theField);
  848.     InitCursor();
  849.     if (status==1) {
  850.         status = DoListDialog();
  851.         if (status==1) GetListSelection(theResult);
  852.         else if (status==2) strcpy(theResult,userButton);
  853.         else strcpy(theResult,"");
  854.     }
  855.     else strcpy(theResult,"Can't find dialog resource 1345 for XScrollBox XFCN");
  856.     len = 1+strlen(theResult);
  857.     resultHandle = NewHandle(len);
  858.     HLock(resultHandle);
  859.     BlockMove(theResult,*resultHandle,len);
  860.     HUnlock(resultHandle);
  861.     paramPtr->returnValue = resultHandle;
  862.     for (i=0;i<5;i++) HUnlock (paramPtr->params[i]);
  863.     return;
  864. }
  865.  
  866. /* this is the entry point for the XFCN */
  867.  
  868. pascal void main(paramPtr)
  869. XCmdBlockPtr    paramPtr;
  870. {
  871.     RememberA4();
  872.     XCMDSetupA4();          /* do this if you have global variables */
  873.     XScrollBox(paramPtr);       /* run the main event loop */   
  874.     PrepareToExit();        /* tidy up */
  875.     XCMDRestoreA4();        /* and this also */
  876.     return;
  877. }
  878.  
  879.  
  880.